#pragma once

// class declarations
class CogGrammar;
class CogEvolver; // pointer only

// -----

#include "CogEvaluator.h"
#include "CogParameters.h"
#include "CogProductionPool.h"
#include "CogCache.h"

// ------------------------------------------------------------------------------------------

class CogGrammar
{
public:
	CogGrammar();

	size_t build();

	CogProduction* forceInstantiate(CogProduction* oldrule, size_t ntSize = 0);
	CogProduction* mutate(CogProduction* pRule);
	
	void initialize(CogEvolver* _pEvolver);
	void clearInstancePools();
	void clearUnusedInstances() { rulePool.removeUnusedInstances(); }
	size_t getInstanceSize() const { return rulePool.getInstanceSize(); }
	size_t getTemplateSize() const { return rulePool.getTemplateSize(); }
	void computeInstanceUsage() { rulePool.computeInstanceUsage(); }

	CogProductionPool* addPool(const string& label, CogProductionPool* pParentPool);
	CogProductionPool* getPool(const string& label, CogProductionPool* pParentPool);
	uint32_t addId(const string& label, CogProductionPool* pParentPool);
	uint32_t getId(const string& label, CogProductionPool* pParentPool);
	CogProductionPool* getPool() { return &rulePool; }
	bool getTerminalId(const string& label, uint32_t& id) const;
	bool getTerminalLabel(uint32_t id, string& label) const;

	bool fromStream(istream &in, CogArgumentType addedType = COGARG_ANY);
	void toStream(ostream &out, CogArgumentType addedType = COGARG_ANY) const;

	// data:
	CogEvolver* pEvolver;
	vector<CogProduction*> startingTemplates;
	CogCache cache;
	
private:
	CogProduction* instantiate(CogProduction* oldrule, size_t ntSize);
	CogProduction* mutate(CogProduction* pRule, uint32_t curIdx, uint32_t targetIdx, size_t depth);

	// data:
	CogProductionPool rulePool;
};

// ------------------------------------------------------------------------------------------